package v9.assist.script

import sample.ui.AppDispatchers
import sample.ui.Properties
import sample.ui.ConsoleLayout
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.script.Block
import kotlinx.coroutines.script.C
import kotlinx.coroutines.script.Controller
import kotlinx.coroutines.script.Controller.Companion.processExitGame
import kotlinx.coroutines.script.accAutoAtk
import kotlinx.coroutines.script.tes.DiskLogUtils
import kotlinx.coroutines.script.tes.appScopeLaunch
import kotlinx.coroutines.script.tes.printLog
import kotlinx.coroutines.script.tes.pt
import kotlinx.coroutines.script.tes.random
import kotlinx.coroutines.script.tes.readByDisk
import kotlinx.coroutines.script.tes.shake
import kotlinx.coroutines.script.tes.toast
import v9.assist.access.accClick
import v9.assist.access.accPathfinding
import v9.assist.access.btnApplyAccept
import v9.assist.access.btnApplyMenu
import v9.assist.access.btnApplyPopMenu
import v9.assist.access.btnApplyRefuse
import v9.assist.access.btnCenterTop
import v9.assist.access.btnCloseable
import v9.assist.access.btnEditFriendClose
import v9.assist.access.btnInteract
import v9.assist.access.btnInviteBlackClose
import v9.assist.access.btnInviteCancel
import v9.assist.access.btnInviteConfirm
import v9.assist.access.btnPopApplyClose
import v9.assist.access.btnPopTxtCancel
import v9.assist.access.btnPopTxtConfirm
import v9.assist.access.btnRandomBuff
import v9.assist.access.btnReviveByOtherCancel
import v9.assist.access.btnReviveInCity
import v9.assist.access.btnSceneHideState
import v9.assist.access.btnSceneInviteGroupAllClose
import v9.assist.access.btnScreenCenter
import v9.assist.access.btnSelectRole
import v9.assist.access.btnSkipAnim
import v9.assist.access.releaseLastGestures

import v9.assist.analyst.PAGE_APPLY
import v9.assist.analyst.PAGE_APPLY_EMPTY
import v9.assist.analyst.PAGE_BASE_MENU
import v9.assist.analyst.PAGE_BE_INVITED
import v9.assist.analyst.PAGE_BE_INVITED_BLACK_GROUP
import v9.assist.analyst.PAGE_BOSS_DIRECT_OR_BUFF
import v9.assist.analyst.PAGE_CLOSEABLE
import v9.assist.analyst.PAGE_EDIT_FRIEND_NAME
import v9.assist.analyst.PAGE_INITIAL
import v9.assist.analyst.PAGE_MAIN
import v9.assist.analyst.PAGE_POP_TEXT
import v9.assist.analyst.PAGE_REVIVE
import v9.assist.analyst.PAGE_REVIVE_BY_OTHER
import v9.assist.analyst.PAGE_ROOT_ENTER
import v9.assist.analyst.PAGE_ROOT_ENTER_TIP
import v9.assist.analyst.PAGE_SCENE_COMPLETED
import v9.assist.analyst.PAGE_SCENE_ENTER
import v9.assist.analyst.PAGE_SCENE_GROUP_INVITE_PLAYER
import v9.assist.analyst.PAGE_SELECT_ROLE
import v9.assist.analyst.PAGE_SKIP
import v9.assist.analyst.PAGE_TALK_BLACKSMITH
import v9.assist.analyst.PAGE_TALK_NPC
import v9.assist.analyst.anaClearSceneSettle
import v9.assist.analyst.anaLastHasBackpack100Ts
import v9.assist.analyst.anaLastHasEnemyBossNameTs
import v9.assist.analyst.anaLastHasEnemyNameTs
import v9.assist.analyst.anaLastHasInteractTs
import v9.assist.analyst.anaLastSMapFBFeature10Ts
import v9.assist.analyst.anaLastSMapFBFeature11Ts
import v9.assist.analyst.anaLastSMapFBFeature13Ts
import v9.assist.analyst.anaLastSMapFBFeature14Ts
import v9.assist.analyst.anaLastSMapFBFeature1Ts
import v9.assist.analyst.anaLastSMapFBFeature3Ts
import v9.assist.analyst.anaLastSMapFBFeature4Ts
import v9.assist.analyst.anaLastSMapFBFeature7Ts
import v9.assist.analyst.anaLastSMapFBFeature8Ts
import v9.assist.analyst.anaLastSMapFBFeature9Ts
import v9.assist.analyst.anaLastSMapFBTargetSampleRightTs
import v9.assist.analyst.anaLastSceneSettleTs
import v9.assist.analyst.anaUpdateExcludeEnemyName
import v9.assist.analyst.setupAnalystScene
import v9.assist.analyst.analystInitialized
import v9.assist.analyst.angleByRoad
import v9.assist.analyst.blockBlacksmith
import v9.assist.analyst.blockBlueDoor
import v9.assist.analyst.blockEliteEnemyBoss
import v9.assist.analyst.bsAcceptApply
import v9.assist.analyst.bsAcceptInvite
import v9.assist.analyst.bsBossBeside
import v9.assist.analyst.bsEnemy
import v9.assist.analyst.bsHasApplyDot
import v9.assist.analyst.bsHasEnemy
import v9.assist.analyst.bsHasInteract
import v9.assist.analyst.bsHasReviveRightBtn
import v9.assist.analyst.bsHasTransmitting
import v9.assist.analyst.bsPage
import v9.assist.analyst.bsPlayerHpLosing
import v9.assist.analyst.bsSceneSettle
import v9.assist.analyst.bsSceneSettleBlacksmith
import v9.assist.analyst.counterActionStopped
import v9.assist.analyst.fsInfo

import v9.assist.analyst.lastEliteEnemyBossTs
import v9.assist.analyst.lastSMapTargetToBossTs
import kotlin.math.max

private var scriptInError = false
private var n: Long? = null // 检查CDK用的时间戳标记
private var job: Job? = null

private var sLastFeature1Ts = 0L // 副本船内P2起点
private var sLastFeature2Ts = 0L // 水手路线
private var sLastFeature3Ts = 0L // 周围无路
private var sLastFeature4Ts = 0L // 起点小船

private var sLastFeature7Ts = 0L //
private var sLastFeature8Ts = 0L //
private var sLastFeature9Ts = 0L // boss前卡住
private var sLastFeature10Ts = 0L // 遇难的船长
private var sLastFeature11Ts = 0L // 水手猜测
private var sLastFeature12Ts = 0L // 补偿移动
private var sLastFeature13Ts = 0L // 副本起点
private var sLastFeature14Ts = 0L // 卡笼子
private var sLastFeature15Ts = 0L // 周围无路连续30秒无敌人.模拟出开最终boss

private var flagSkipToNpc = false // 击破船长Boss移动到npc
private var flagGuideTip = 0


fun startSceneFB() {
    job?.cancel()
    job = appScopeLaunch(AppDispatchers.Script) {
        scriptInError = false
        xCounterNetRetry = Properties.netRetryCount
        xLastAtvTs = System.currentTimeMillis()
        xLastSceneEnterTs = System.currentTimeMillis() // 现在只记录副本开始时间
        setupAnalystScene(C.S_FB)
        anaUpdateExcludeEnemyName("")
        n = System.currentTimeMillis()
        delay(200) 
        while(Controller.isRunning && !scriptInError) {
            checkScriptError()
            if (!analystInitialized) {
                printLog { "Script invoking not ready" }
                ConsoleLayout.outputText("等待首帧截屏.连续出现重启脚本")
                toast("等待首帧截屏.连续出现重启脚本")
                delay(1000) // 刚开始没准备好
            } else {
                val timestamp = System.currentTimeMillis()
                processFsFB()
                val using = System.currentTimeMillis() - timestamp
                if (using < 10) delay(if (bsPage == PAGE_INITIAL) 800L.shake(50) else 200L.shake(5))
            }
        }
    }
}

fun stopSceneFB() {
    xSceneHideState = false
    xBossDirectOrBuff = false
    xLastAtvTs = 0 // 不能少
    job?.cancel()
    anaClearSceneSettle()
}

suspend fun processFsFB() {
    fsInfo.also { if (bsPage != SCRIPT_MAIN) printLog { "processFs $it" } }

    if (bsPage == PAGE_BE_INVITED) {
        val widget = if (bsAcceptInvite) btnInviteConfirm else btnInviteCancel
        accClick(widget, afterDelay = 500)
        random.nextInt(360).also { 
            listOf(it, it, it, it).forEachIndexed { index, i -> 
                printLog { "script 随机移动 $index" }
                accPathfinding(i)
            }
            releaseLastGestures()
        }
    } else if (bsPage == PAGE_REVIVE) {
        if (bsHasReviveRightBtn) {
            accClick(btnReviveInCity, afterDelay = 333) // 远古复活不在船上.卡海里了
        } else {
            accClick(btnReviveInCity, afterDelay = 333)
            if (xBossDirectOrBuff) xLastBossDirectOrBuffTs = System.currentTimeMillis()
        }
        xLastAtvTs = System.currentTimeMillis()
        xLastReviveTs = System.currentTimeMillis()
    } else if (bsPage == PAGE_SCENE_ENTER) {
        accSceneEnter()
        flagSkipToNpc = false
    } else if (bsPage == PAGE_BASE_MENU) {
        accClick(btnScreenCenter, afterDelay = 2000)
    } else if (bsPage == PAGE_SKIP) {
        delay(500)
        accClick(btnSkipAnim, afterDelay = 2500)
        xLastAtvTs = System.currentTimeMillis()

        // 水手skip 可能是刚击破boss. 或者拉过来的
        if (System.currentTimeMillis() - sLastFeature2Ts > 60000
            && System.currentTimeMillis() - sLastFeature4Ts > 6000
            && System.currentTimeMillis() - anaLastSMapFBFeature13Ts > 3000
            && System.currentTimeMillis() - anaLastSMapFBFeature7Ts > 3000) {
            flagSkipToNpc = true

            if (flagGuideTip < 6) {
                flagGuideTip++
                toast("即将固定路线前往水手npc.角色移速125%-135%最佳.请根据实际情况调整角色移速 $flagGuideTip")
            }

            delay(1800)
            listOf(100, 110, 100, 110, 100, 110, 110, 110,).forEachIndexed { index, i ->
                if (System.currentTimeMillis() - anaLastHasEnemyBossNameTs > 1000) {
                    printLog { "scriptFB 节点.P2水手a $index" }
                    accPathfinding(i, disableSkillAlways = true)
                }
            }
            releaseLastGestures()
            repeat(4) { delay(1000L) } // 等水手到位
            listOf(265, 270, 265, 270).forEachIndexed { index, i ->
                if (System.currentTimeMillis() - anaLastHasEnemyBossNameTs > 1000) {
                    printLog { "scriptFB 节点.P2水手b $index" }
                    accPathfinding(i, if (index >= 0) btnInteract else null)
                }
            }
            releaseLastGestures()
            repeat(1) { delay(1000L) } // 等水手到位
            listOf(25, 30, 25).forEachIndexed { index, i ->
                if (System.currentTimeMillis() - anaLastHasEnemyBossNameTs > 1000) {
                    printLog { "scriptFB 节点.P2水手d $index" }
                    accPathfinding(i, if (index >= 0) btnInteract else null)
                }
            }
            if (flagGuideTip < 6) {
                toast("若没有触发对话水手npc.注意调整尝试角色移速125%-135%最佳.还有问题请视频片段反馈 $flagGuideTip")
            }
            releaseLastGestures()
            repeat(3) {
                if (System.currentTimeMillis() - anaLastHasEnemyBossNameTs > 1000) {
                    accClick(btnCenterTop, afterDelay = 1200)
                }
            }
            delay(2500L) // 等触手出来
            if (System.currentTimeMillis() - anaLastHasEnemyNameTs > 2000) delay(2000L) // 这里还要等2秒.等boss出来减少不必要往下走
            sLastFeature2Ts = System.currentTimeMillis()
        }

    } else if (bsPage == PAGE_POP_TEXT) {
        accClick(btnPopTxtCancel, afterDelay = 2400)
        listOf(45, 45, 45, 45, 45, 45, 45).forEachIndexed { index, i ->
            printLog { "script 防止卡地图移动 $index" }
            if (bsHasEnemy || bsPlayerHpLosing || bsBossBeside) accAutoAtk(i)
            else accPathfinding(i)
        }
        accClick(btnInteract, afterDelay = 1500)
        accClick(btnPopTxtConfirm, afterDelay = 2000) // 如果是在外面的入口卡住
        xLastAtvTs = System.currentTimeMillis() // 延长时间
    } else if (bsPage == PAGE_BE_INVITED_BLACK_GROUP) {
        delay(500)
        accClick(btnInviteBlackClose, afterDelay = 1500)
    } else if (bsPage == PAGE_EDIT_FRIEND_NAME) {
        delay(500)
        accClick(btnEditFriendClose, afterDelay = 1500)
        random.nextInt(360).also { 
            listOf(it, it, it, it).forEachIndexed { index, i -> 
                printLog { "script 随机移动 $index" }
                accPathfinding(i)
            }
            releaseLastGestures()
        }
    } else if (bsPage == PAGE_SCENE_GROUP_INVITE_PLAYER) {
        delay(500)
        accClick(btnSceneInviteGroupAllClose, afterDelay = 1500)
        random.nextInt(360).also { 
            listOf(it, it, it, it).forEachIndexed { index, i -> 
                printLog { "script 随机移动 $index" }
                accPathfinding(i)
            }
            releaseLastGestures()
        }
    } else if (bsPage == PAGE_TALK_BLACKSMITH || bsPage == PAGE_SCENE_COMPLETED
        || bsSceneSettleBlacksmith || bsSceneSettle
    ) {
        if (bsEnemy == "Y" || bsEnemy == "B" || bsEnemy == "P" || blockEliteEnemyBoss != null
            && System.currentTimeMillis() - sLastFeature34Ts > 1000) {
            anaClearSceneSettle()
            sLastFeature34Ts = System.currentTimeMillis()
        }
        else {
            xLastAtvTs = System.currentTimeMillis()
            sceneHandlingSettle(
                blacksmithBy = { blacksmithByBlueDoor(blockBlueDoor) ?: blacksmithByBlacksmith(blockBlacksmith) },
                exitBy = { exitByBlueDoor(blockBlueDoor) ?: exitByBlacksmith(blockBlacksmith) }
            )
        }
    } else if (bsPage == PAGE_TALK_NPC) {
        delay(500)
        accClick(btnScreenCenter, afterDelay = 1500)
        random.nextInt(360).also { 
            listOf(it, it, it, it).forEachIndexed { index, i -> 
                printLog { "script 随机移动 $index" }
                accPathfinding(i)
            }
            releaseLastGestures()
        } // 应该没有这段

    } else if (bsPage == PAGE_APPLY_EMPTY) {
        accClick(btnPopApplyClose, afterDelay = 1000)
    } else if (bsPage == PAGE_APPLY) {
        accClick(if (bsAcceptApply) btnApplyAccept else btnApplyRefuse, afterDelay = 1000)
    } else if (bsPage == PAGE_SELECT_ROLE) {
        accClick(btnSelectRole, afterDelay = 1500)
    } else if (bsPage == PAGE_CLOSEABLE) {
        delay(500)
        accClick(btnCloseable, afterDelay = 3000)
        xLastCloseableTs = System.currentTimeMillis()
    } else if (bsPage == PAGE_BOSS_DIRECT_OR_BUFF) {
        delay(500)
        accClick(btnRandomBuff, afterDelay = 2000)
        xLastBossDirectOrBuffTs = System.currentTimeMillis()
        xBossDirectOrBuff = true
    } else if (bsPage == PAGE_REVIVE_BY_OTHER) {
        accClick(btnReviveByOtherCancel, afterDelay = 1500)
    } else if (bsPage == PAGE_ROOT_ENTER_TIP || bsPage == PAGE_ROOT_ENTER) {
        tryEnterByRelaunch()
    } else if (bsPage == PAGE_MAIN) { // 主页操作
        if (bsHasEnemy || bsPlayerHpLosing || bsBossBeside) {
            sceneFBSpecialHandling1()
            accAutoAtk(angleByRoad)
            xLastAtvTs = System.currentTimeMillis()
            if (bsHasEnemy) xLastAtkTs = System.currentTimeMillis()
        } else if (
            (System.currentTimeMillis() - xLastBossDirectOrBuffTs < 30000 || (System.currentTimeMillis() - xLastReviveTs < 30000 && xBossDirectOrBuff))
            && System.currentTimeMillis() - anaLastHasEnemyNameTs > 3000
            && blockBlueDoor != null) {
            printLog { "scriptFB 直通直接去bossA" }
            listOf(100, 100, 100, 100, 100, 100,
                170, 190,).forEachIndexed { index, i ->
                printLog { "scriptFB 直通直接去bossA $index" }
                accPathfinding(i, if (index >= 6) btnInteract else null)
            }
            releaseLastGestures() // 换场景了
            delay(2000L)
            listOf(0, 0).forEachIndexed { index, i ->
                printLog { "scriptFB 直通直接去bossA 船长互动 $index" }
                accPathfinding(i, if (index >= 1) btnInteract else null)
            }
        } else if (bsHasTransmitting
            && !bsPlayerHpLosing
            && System.currentTimeMillis() - anaLastHasInteractTs < 9000) {
            // 开门流程
            xCounterInteract = 0
            delay(500)
        } else if (System.currentTimeMillis() - anaLastHasBackpack100Ts < 50000
            && (System.currentTimeMillis() - xLastAtkTs > 3000 || System.currentTimeMillis() - anaLastSceneSettleTs < 10000)
            && System.currentTimeMillis() - sLastFeature29Ts > 50000) {
            printLog { "script 满背包尝试分解" }
            tryPetBlacksmithSubmit()
            sLastFeature29Ts = System.currentTimeMillis()
        } else if (bsHasInteract && !bsPlayerHpLosing
            && System.currentTimeMillis() - xLastUnknownTs > 8000
            && System.currentTimeMillis() - xLastSceneEnterTs > 12000
            && System.currentTimeMillis() - lastEliteEnemyBossTs > 16000  // 击杀boss后不要乱点
            && System.currentTimeMillis() - anaLastHasEnemyBossNameTs > 16000 // 这个风暴boss没有图标.通关容易出去
            && System.currentTimeMillis() - xLastBossDirectOrBuffTs > 20000
            && !bsSceneSettle && !bsSceneSettleBlacksmith
            && System.currentTimeMillis() - anaLastSceneSettleTs > 15000
            && System.currentTimeMillis() - xLastCloseableTs > 10000) {
            accClick(btnInteract, afterDelay = 0L)
            xCounterInteract++
            if (xCounterInteract % 2 == 0) { // 超过？秒即可。 互动进度条 6秒够了
                delay(500)
                accPathfinding(angleByRoad)
                accPathfinding(angleByRoad)
                accPathfinding(angleByRoad)
                accPathfinding(random.nextInt(360))
            }
        } else if (bsHasApplyDot && Properties.inviteAutoAccept != 0) {
            accClick(btnApplyMenu, afterDelay = 500)
            accClick(btnApplyPopMenu, afterDelay = 1000)
        } else {
            // 寻路流程
            xCounterInteract = 0
            sceneFBSpecialHandling1()
            accPathfinding(sceneAngleByRoad())
        }
    } else if (bsPage != PAGE_MAIN) {
        scriptHandlingUnknown()
    }
}


suspend fun sceneFBSpecialHandling1() {
    if (System.currentTimeMillis() - xLastAtkTs > 240000
        && System.currentTimeMillis() - xLastAtvTs > 240000
        && System.currentTimeMillis() - xLastSceneExitTs > 120000) {
        printLog { "scriptFB 节点.超时退出" }
        sceneExit()
    } else if (counterActionStopped > 30 && System.currentTimeMillis() - xLastAtkTs > 3000
        && System.currentTimeMillis() - sLastFeature33Ts > 60000) {
        printLog { "script 节点.原地不动." }
        releaseLastGestures()
//        accClick(btnSmallMap, afterDelay = 2000)
        counterActionStopped = 0
        sLastFeature33Ts = System.currentTimeMillis()
    } else if (System.currentTimeMillis() - anaLastSMapFBFeature1Ts < 2000
        && System.currentTimeMillis() - sLastFeature1Ts > 10000) {
        if (System.currentTimeMillis() - xLastAtkTs > 60000
            && System.currentTimeMillis() - xLastAtvTs > 60000
            && System.currentTimeMillis() - sLastFeature11Ts > 30000) {
            // 可能是卡水手了
            listOf(135, 130, 135, 130, 135, 130, 135, 130, 135, 130,
                180, 170, 180, 190, 180, 190,
                210, 240, 270, 270, 270, 280, 300, 310, 320,
                290, 300, 290, 300, 290, 300, 290, 300, 290, 300, 290, 300,
                290, 300, 290, 300, 290, 300, 290, 300, 290, 300, 290, 300,
                290, 300, 290, 300,).forEachIndexed { index, i ->
                printLog { "scriptFB 节点.P2起点水手a $index" }
                accPathfinding(i)
            }
            listOf(80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 90,).forEachIndexed { index, i ->
                printLog { "scriptFB 节点.P2起点水手b $index" }
                accPathfinding(i, if (index > 10) btnInteract else null)
            }
            listOf(250, 260, 275).forEachIndexed { index, i ->
                printLog { "scriptFB 节点.P2起点水手c $index" }
                accPathfinding(i, btnInteract)
            }
            sLastFeature11Ts = System.currentTimeMillis()
        } else {
            listOf(135, 130, 135, 130,
                180, 170, 180, 190, 180,
                210, 240, 270, 270, 270, 280, 300, 310, 320,
                290, 300, 290, 300, 290, 300, 290, 300, 290, 300, 290, 300,
                290, 300, 290, 300, 290, 300, 290, 300, ).forEachIndexed { index, i ->
                printLog { "scriptFB 节点.P2起点A $index" }
                accPathfinding(i)
            }
            listOf(290, 300, 290, 300, 290, 300,).forEachIndexed { index, i ->
                printLog { "scriptFB 节点.P2起点B $index" }
                if (bsHasEnemy || bsPlayerHpLosing || bsBossBeside) accAutoAtk(i)
                else accPathfinding(i) // 避免一动距离不够
            }
            listOf(350, 0, 0, 350, 15, 0, 350, 15, 0, 350, 5, 0,
                330, 320, 330, 320, 330, 320).forEachIndexed { index, i ->
                printLog { "scriptFB 节点.P2起点C $index" }
                accPathfinding(i)
            }
        }
        sLastFeature1Ts = System.currentTimeMillis()
    } else if (System.currentTimeMillis() - anaLastSMapFBFeature3Ts < 2000
        && System.currentTimeMillis() - sLastFeature3Ts > 2000) {

        if  (flagSkipToNpc) {
            // 正常流程 倒数第二个章鱼黑
            val a =  175
            val b = 255
            listOf(a, a, a, a, a, a, a, a, b, b + 30, b + 20, b, b, b + 30, b + 20, b,
                a, a, a, a, a, a, a, a, b, b + 30, b + 20, b, b, b + 30, b + 20, b,).forEachIndexed { index, i ->
                if (System.currentTimeMillis() - anaLastSMapFBFeature13Ts > 2000) {
                    printLog { "scriptFB 节点.周围无路 [$flagSkipToNpc] $index ($i)" }
                    repeat(4) { if (System.currentTimeMillis() - anaLastHasEnemyBossNameTs < 1000) accAutoAtk(i) }
                    if (bsHasEnemy || bsPlayerHpLosing || bsBossBeside) accAutoAtk(i)
                    else if (index % 11 == 0) accAutoAtk(i) // 每隔11个点强制使用1次技能
                    else accPathfinding(i)
                }
            }
        } else {
            // 直接打最后的boss没地图
            val a =  20
            val b =  330 // 最终boss.直通Boss
            listOf(a, a, a, a, a, a, a, a, b, b, b, b, b, b, b, b,
                a, a, a, a, a, a, a, a, b, b, b, b, b, b, b, b,).forEachIndexed { index, i ->
                if (System.currentTimeMillis() - anaLastSMapFBFeature13Ts > 2000) {
                    printLog { "scriptFB 节点.周围无路 [$flagSkipToNpc] $index ($i)" }
                    repeat(4) { if (System.currentTimeMillis() - anaLastHasEnemyBossNameTs < 1000) accAutoAtk(i) }
                    if (bsHasEnemy || bsPlayerHpLosing || bsBossBeside) accAutoAtk(i)
                    else accPathfinding(i)
                }
            }
        }

        sLastFeature3Ts = System.currentTimeMillis()

        if (System.currentTimeMillis() - xLastAtkTs > 36000
            && System.currentTimeMillis() - sLastFeature15Ts > 36000) {
            // 这里长时间无战斗模拟最终boss开启
            listOf(55, 60, 55, 60, 55, 60, 55, 60, 55, 60, 55, 60,).forEachIndexed { index, i ->
                if (System.currentTimeMillis() - anaLastSMapFBFeature13Ts > 2000) {
                    printLog { "scriptFB 节点.周围无路 可能是最终Boss $index" }
                    if (bsHasEnemy || bsPlayerHpLosing || bsBossBeside) accAutoAtk(i)
                    else accPathfinding(i)
                }
            }
            listOf(0, 30, 0, 260, 260, 255, 260, 260).forEachIndexed { index, i ->
                // 不增加.就移动
                if (System.currentTimeMillis() - anaLastSMapFBFeature13Ts > 2000) {
                    printLog { "scriptFB 节点.周围无路 模拟遇难的船长 $index" } // 遇到门就互动
                    if (bsHasEnemy || bsPlayerHpLosing || bsBossBeside) accAutoAtk(i)
                    else accPathfinding(i, if (index > 1) btnInteract else null)
                }
            }
            sLastFeature15Ts = System.currentTimeMillis()
        }
    } else if (System.currentTimeMillis() - anaLastSMapFBFeature8Ts < 2000
        && System.currentTimeMillis() - sLastFeature8Ts > 6000) {
        listOf(90, 100, 80, 90, 100, 90, 100, 90, 100, 120).forEachIndexed { index, i ->
            printLog { "scriptFB 节点.副本外入口 $index" } // 遇到门就互动
            accPathfinding(i, if (index > 3) btnInteract else null)
        }
        accClick(btnPopTxtConfirm, afterDelay = 2000) // 如果是在外面的入口卡住
        sLastFeature8Ts = System.currentTimeMillis()
    } else if (System.currentTimeMillis() - anaLastSMapFBFeature4Ts < 2000
        && System.currentTimeMillis() - sLastFeature4Ts > 4000) {
        listOf(30, 40, 30, 40, 20, 0, 0, 10, 330, 270,).forEachIndexed { index, i ->
            printLog { "scriptFB 节点.起点小船 $index" } // 遇到门就互动
            if (bsHasEnemy || bsPlayerHpLosing || bsBossBeside) accAutoAtk(i)
            else accPathfinding(i)
        }
        sLastFeature4Ts = System.currentTimeMillis()
    } else if (System.currentTimeMillis() - anaLastSMapFBFeature7Ts < 2000
        && System.currentTimeMillis() - sLastFeature7Ts > 6000) {
        listOf(90, 120).forEachIndexed { index, i ->
            printLog { "scriptFB 节点.直通 $index" } // 遇到门就互动
            accPathfinding(i, btnInteract)
        }
        releaseLastGestures() // 换场景了
        delay(2000L)
        listOf(0, 0).forEachIndexed { index, i ->
            printLog { "scriptFB 直通直接去bossA 船长互动 $index" }
            accPathfinding(i, if (index >= 1) btnInteract else null)
        }
        sLastFeature7Ts = System.currentTimeMillis()
    } else if (System.currentTimeMillis() - anaLastSMapFBFeature9Ts < 2000
        && System.currentTimeMillis() - sLastFeature9Ts > 4000) {
        listOf(180, 160, 180, 160, 170, 160, 120, 135, 180, 140).forEachIndexed { index, i ->
            if (System.currentTimeMillis() - anaLastHasEnemyNameTs > 1000
                && System.currentTimeMillis() - anaLastSMapFBFeature1Ts > 1000) {
                printLog { "scriptFB 节点.大船甲板右侧 $index" } // 遇到门就互动. P2了就停掉
                if (bsHasEnemy || bsPlayerHpLosing || bsBossBeside) accAutoAtk(i)
                else accPathfinding(i, if (index > 1) btnInteract else null)
            }
        }

        if (System.currentTimeMillis() - xLastAtkTs > 16000) {
            listOf(270, 270, 270, 270, 270,
                320, 320, 320, 320, 320, 320, 320, 320,320, 320,
                270, 270, 300).forEachIndexed { index, i ->
                if (System.currentTimeMillis() - anaLastSMapFBFeature1Ts > 1000) {
                    printLog { "scriptFB 节点.大船甲板右侧 B可能大副还在 $index" } // 遇到门就互动. P2了就停掉
                    if (bsHasEnemy || bsPlayerHpLosing || bsBossBeside) accAutoAtk(i)
                    else accPathfinding(i)
                }
            }
        }

        sLastFeature9Ts = System.currentTimeMillis()
    } else if (System.currentTimeMillis() - anaLastSMapFBFeature10Ts < 2000
        && System.currentTimeMillis() - sLastFeature10Ts > 6000) {
        listOf(0, 30, 0, 260, 260, 255, 260, 260).forEachIndexed { index, i ->
            // 不增加.就移动
            printLog { "scriptFB 节点.遇难的船长 $index" } // 遇到门就互动
            if (bsHasEnemy || bsPlayerHpLosing || bsBossBeside) accAutoAtk(i)
            else accPathfinding(i, if (index > 1 && System.currentTimeMillis() - xLastAtkTs > 7000) btnInteract else null)
        }
        sLastFeature10Ts = System.currentTimeMillis()
    } else if (System.currentTimeMillis() - anaLastSMapFBFeature11Ts < 2000
        && System.currentTimeMillis() - sLastFeature11Ts > 6000) {
        listOf(0, 355, 5, 355, 0, 40).forEachIndexed { index, i ->
            if (System.currentTimeMillis() - lastSMapTargetToBossTs > 2000) {
                printLog { "scriptFB 节点.调整去大船 $index" } // 遇到门就互动
                if (bsHasEnemy || bsPlayerHpLosing || bsBossBeside) accAutoAtk(i)
                else accPathfinding(i, if (index > 1) btnInteract else null)
            }
        }
        sLastFeature11Ts = System.currentTimeMillis()
    } else if (System.currentTimeMillis() - anaLastSMapFBTargetSampleRightTs < 2000
        && System.currentTimeMillis() - xLastAtkTs > 3000
        && System.currentTimeMillis() - sLastFeature12Ts > 4000
        && System.currentTimeMillis() - lastEliteEnemyBossTs > 8000
        && System.currentTimeMillis() - anaLastSMapFBFeature4Ts in 6000 .. 120000) {
        listOf(180, 170, 180).forEachIndexed { index, i ->
            printLog { "scriptFB 节点.调整去船舱 $index" } // 遇到门就互动
            if (bsHasEnemy || bsPlayerHpLosing || bsBossBeside) accAutoAtk(i)
            else accPathfinding(i, if (index > 1) btnInteract else null)
        }
        sLastFeature12Ts = System.currentTimeMillis()
    } else if (System.currentTimeMillis() - anaLastSMapFBFeature13Ts < 2000
        && System.currentTimeMillis() - sLastFeature13Ts > 6000) {
        printLog { "scriptFB 节点.风暴路线 是起点" }
        if (!xSceneHideState) {
            printLog { "script. 收起副本状态" }
            accClick(btnSceneHideState, afterDelay = 500)
            xSceneHideState = true
        }
        sLastFeature13Ts = System.currentTimeMillis()
    } else if (System.currentTimeMillis() - anaLastSMapFBFeature14Ts < 2000
        && System.currentTimeMillis() - sLastFeature14Ts > 6000) {
        listOf(165, 165, 180, 140, 110, 90, 90, 70, 90).forEachIndexed { index, i ->
            printLog { "scriptFB 节点.卡笼子 $index" } // 遇到门就互动
            if (bsHasEnemy || bsPlayerHpLosing || bsBossBeside) accAutoAtk(i)
            else accPathfinding(i)
        }
        sLastFeature14Ts = System.currentTimeMillis()
    }
}


private fun blacksmithByBlueDoor(blueDoor: Block?): Block? {
    if (blueDoor == null) return null
    return Block("铁匠", blueDoor.x - 22.pt, blueDoor.y + 26.pt, 0, 0)
}
private fun blacksmithByBlacksmith(blacksmith: Block?): Block? {
    if (blacksmith == null) return null
    return Block("铁匠fixed", blacksmith.x - 4.pt, blacksmith.y + 6.pt, 0, 0)
}
private fun exitByBlueDoor(blueDoor: Block?): Block? {
    if (blueDoor == null) return null
    return Block("小地图传送门fixed", blueDoor.x + 3.pt, blueDoor.y - 5.pt, 0, 0)
}
private fun exitByBlacksmith(blacksmith: Block?): Block? {
    if (blacksmith == null) return null
    return Block("小地图传送门By铁匠", blacksmith.x + 20.pt, blacksmith.y - 26.pt, 0, 0)
}

private suspend fun checkScriptError() {
    if (xLastAtvTs == 0L) {
        return
    }
    if (xScriptEndTs > 0 && System.currentTimeMillis() > xScriptEndTs) {
        scriptInError = true
        processExitGame("定时结束(${Properties.stopCountdown}秒)")
        DiskLogUtils.saveToDisk()
    }
    val timeout = Properties.scriptStopTimeout * 1000L   // 超过分钟没有敌人停止脚本
    xAtvLeftTime = max(0, timeout - (System.currentTimeMillis() - xLastAtvTs))
    if (System.currentTimeMillis() - xLastAtvTs > timeout) {
        scriptInError = true
        processExitGame("${C.ERROR_END}=${timeout / 1000}")
        DiskLogUtils.saveToDisk()
    }
    val ne = n
    if (ne != null && System.currentTimeMillis() - ne > timeout
        && System.currentTimeMillis() - lastEliteEnemyBossTs > timeout) {
        // 还有一种情况. 就是已经运行了x分钟了.但是没有boss 可能卡遗迹了
        scriptInError = true
        processExitGame("${C.ERROR_END}=BossLoss")
        DiskLogUtils.saveToDisk()
    }
    if (ne != null && System.currentTimeMillis() - ne > 198123L) {
        val sp = "j#s#l#t#z#m#p#e#r#a".split("#")
        var pass = true
        sp.forEach {
            if (pass && readByDisk(it).isNullOrEmpty()) pass = false
        }
        printLog { "j#s#l#t#z#m#p#e#r#a [pass:$pass]" }
        if (!pass) scriptInError = true
        else n = null
    }
}